package com.xuelang.pipeline.infrastructure.task.repository;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.task.dto.TaskQuery;
import com.xuelang.pipeline.domain.task.Task;
import com.xuelang.pipeline.domain.task.repository.TaskRepository;
import com.xuelang.pipeline.infrastructure.task.converter.TaskToTaskDOConverter;
import com.xuelang.pipeline.infrastructure.task.dataobject.TaskDO;
import com.xuelang.pipeline.infrastructure.task.mapper.TaskMapper;
import dm.jdbc.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * 流水线任务仓库实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Slf4j
@Repository
public class TaskRepositoryImpl implements TaskRepository {

    @Autowired
    TaskMapper taskMapper;

    @Override
    public PageRecord<Task> pageList(long currentPage, long pageSize, TaskQuery taskQuery) {
        currentPage = currentPage < 1 ? 1 : currentPage;
        pageSize = pageSize < 1 ? 10 : pageSize;
        Page<Task> page = new Page<>(currentPage, pageSize);
        MPJLambdaWrapper<TaskDO> wrapper = new MPJLambdaWrapper<TaskDO>();
        if (taskQuery != null) {
            wrapper.selectAll(TaskDO.class)
                    .and(StrUtil.isNotBlank(taskQuery.getCondition()), wp -> wp
                            .like(TaskDO::getName, taskQuery.getCondition()).or()
                            .like(TaskDO::getCode, taskQuery.getCondition()))
                    .apply(StrUtil.isNotBlank(taskQuery.getStartDate()), "DATE_FORMAT(t.create_time,'%Y-%m-%d')>={0}", taskQuery.getStartDate())
                    .apply(StrUtil.isNotBlank(taskQuery.getStartDate()), "DATE_FORMAT(t.create_time,'%Y-%m-%d')<={0}", taskQuery.getEndDate())
                    .orderByDesc(TaskDO::getCreateTime);
        }
        taskMapper.selectJoinPage(page, Task.class, wrapper);
        return new PageRecord<>(
                page.getCurrent(),
                page.getSize(),
                page.getTotal(),
                page.getPages(),
                page.getRecords());
    }

    @Override
    public List<Task> list(TaskQuery taskQuery) {
        MPJLambdaWrapper<TaskDO> wrapper = new MPJLambdaWrapper<TaskDO>();
        if (taskQuery != null) {
            wrapper.selectAll(TaskDO.class)
                    .and(StrUtil.isNotBlank(taskQuery.getCondition()), wp -> wp
                            .like(TaskDO::getName, taskQuery.getCondition()).or()
                            .like(TaskDO::getCode, taskQuery.getCondition()))
                    .eq(StrUtil.isNotBlank(taskQuery.getPipelineCode()), TaskDO::getPipelineCode, taskQuery.getPipelineCode())
                    .apply(StrUtil.isNotBlank(taskQuery.getStartDate()), "DATE_FORMAT(t.create_time,'%Y-%m-%d')>={0}", taskQuery.getStartDate())
                    .apply(StrUtil.isNotBlank(taskQuery.getStartDate()), "DATE_FORMAT(t.create_time,'%Y-%m-%d')<={0}", taskQuery.getEndDate())
                    .orderByDesc(TaskDO::getCreateTime);
        }
        return taskMapper.selectJoinList(Task.class, wrapper);
    }

    @Override
    public Boolean save(Task task) {
        return taskMapper.insert(TaskToTaskDOConverter.INSTANCE.taskToTaskDO(task)) == 1;
    }

    @Override
    public Boolean update(Task task) {
        return taskMapper.update(
                TaskToTaskDOConverter.INSTANCE.taskToTaskDO(task),
                Wrappers.lambdaQuery(TaskDO.class)
                        .eq(TaskDO::getUuid, task.getUuid())) == 1;
    }

    @Override
    public Boolean delete(String uuid) {
        return taskMapper.delete(Wrappers.lambdaQuery(TaskDO.class)
                .eq(TaskDO::getUuid, uuid)) == 1;
    }

    @Override
    public Task query(String uuid) {
        TaskDO taskDO = taskMapper.selectOne(Wrappers.lambdaQuery(TaskDO.class).eq(TaskDO::getUuid, uuid));
        return TaskToTaskDOConverter.INSTANCE.taskDOToTask(taskDO);
    }

    @Override
    public Boolean deleteByPipelineCode(String pipelineCode) {
        return taskMapper.delete(Wrappers.lambdaQuery(TaskDO.class)
                .eq(TaskDO::getPipelineCode, pipelineCode)) >= 0;
    }

    @Override
    public Boolean batchSaveByPipelineTemplateUuid(String pipelineTemplateUuid, String toPipelineCode, String userId) {
        return taskMapper.batchInsertByPipelineTemplateUuid(pipelineTemplateUuid, toPipelineCode, userId) >= 0;
    }

    @Override
    public Boolean existsCode(String pipelineCode, String taskCode) {
        return taskMapper.exists(Wrappers.lambdaQuery(TaskDO.class)
                .eq(TaskDO::getPipelineCode, pipelineCode)
                .eq(TaskDO::getCode, taskCode));
    }

    @Override
    public Boolean existsName(String pipelineCode, String taskCode, String taskName) {
        List<TaskDO> taskDOS = taskMapper.selectList(Wrappers.lambdaQuery(TaskDO.class)
                .eq(TaskDO::getPipelineCode, pipelineCode)
                .eq(TaskDO::getName, taskName));
        if (ObjectUtil.isEmpty(taskDOS)) {
            return false;
        }
        return taskDOS.stream().anyMatch(taskDO -> !StringUtil.equals(taskCode, taskDO.getCode()));
    }
}
